#include "peripheral_uart.h"

//  Update ther previous function for Cortex-M3 not support hard float calculate
void apUART_BaudRateSet(UART_TypeDef* pBase, uint32_t ClockFrequency, uint32_t BaudRate)
{
    uint32_t BaudRateDiv;
    uint32_t BaudIntDiv;
    uint32_t BaudFracDiv;

    BaudRateDiv = (ClockFrequency << 3) / BaudRate;


    /* Calculate integer baud rate register value */
    BaudIntDiv = BaudRateDiv / 128;

    /* Calculate fraction baud rate register value */
    BaudRateDiv -= (BaudIntDiv << 7);
    BaudFracDiv =  (BaudRateDiv + 1) / 2;


    pBase->IntBaudDivisor   = BaudIntDiv;

    if (( BaudIntDiv > 65535 ) || ( BaudIntDiv == 0 ))
        for (;;);

    /* Calculate fractional baud rate register value */
    if ( BaudIntDiv == 65535 )
    {
        pBase->FractBaudDivisor = 0;
    }
    else
    {
        BaudRateDiv -= BaudIntDiv;
        pBase->FractBaudDivisor = BaudFracDiv;
    }

    //--------------------------
    // USER NOTE :
    //
    // ARM UART TRM Page 60 -
    //    The UARTLCR_H, UARTIBRD, and UARTFBRD registers form the single 30-bit
    //    wide UARTLCR Register that is updated on a single write strobe generated by a
    //    UARTLCR_H write. So, to internally update the contents of UARTIBRD or
    //    UARTFBRD, a UARTLCR_H write must always be performed at the end.
    //
    pBase->LineCon_H = pBase->LineCon_H;
}


//
// NOTE : ClockFrequency is freq of UARTCLK
//
uint32_t apUART_BaudRateGet (UART_TypeDef* pBase, uint32_t ClockFrequency)
{
  float BaudRateDiv;
  if (pBase->FractBaudDivisor != 0)
  {
      BaudRateDiv = (float) (((pBase->FractBaudDivisor - 0.5)/64) + pBase->IntBaudDivisor);
      return (uint32_t) (ClockFrequency / BaudRateDiv);
  }
  else
  {
      return (uint32_t) ((ClockFrequency >> 4) / pBase->IntBaudDivisor);
  }
}

//
// User Note :
//   ARM UART TRM Page 53 -
//   The received data character must be read first from the Data Register, UARTDR,
//   before reading the error status associated with that data character from the
//   UARTRSR Register. This read sequence cannot be reversed, because the UARTRSR
//   Register is updated only when a read occurs from the UARTDR Register.
//
uint8_t apUART_Check_Rece_ERROR(UART_TypeDef* pBase)
{
	uint8_t error = 0;

	if ( (pBase->StatusClear >> bsUART_STAT_FRAME) & BW2M(bwUART_STAT_FRAME) )   // FE
		error += 1<<0;

	if ( (pBase->StatusClear >> bsUART_STAT_PARITY) & BW2M(bwUART_STAT_PARITY) )   // PE
	  error += 1<<1;

	if ( (pBase->StatusClear >> bsUART_STAT_BREAK) & BW2M(bwUART_STAT_BREAK) )   // BE
		error += 1<<2;

	if ( (pBase->StatusClear >> bsUART_STAT_OVERRUN) & BW2M(bwUART_STAT_OVERRUN) )   // OE
		error += 1<<3;

	return error;
}

//
uint8_t apUART_Check_RXFIFO_EMPTY(UART_TypeDef* pBase)
{
	return ( (pBase->Flag >> bsUART_RECEIVE_EMPTY) & BW2M(bwUART_RECEIVE_EMPTY) );
}

uint8_t apUART_Check_RXFIFO_FULL(UART_TypeDef* pBase)
{
	return ( (pBase->Flag >> bsUART_RECEIVE_FULL) & BW2M(bwUART_RECEIVE_FULL) );
}

uint8_t apUART_Check_TXFIFO_EMPTY(UART_TypeDef* pBase)
{
	return ( (pBase->Flag >> bsUART_TRANSMIT_EMPTY) & BW2M(bwUART_TRANSMIT_EMPTY) );
}

uint8_t apUART_Check_TXFIFO_FULL(UART_TypeDef* pBase)
{
	return ( (pBase->Flag >> bsUART_TRANSMIT_FULL) & BW2M(bwUART_TRANSMIT_FULL) );
}

uint8_t apUART_Check_BUSY(UART_TypeDef* pBase)
{
	return ( (pBase->Flag >> bsUART_BUSY) & BW2M(bwUART_BUSY) );
}

//  ljl add get Receive Status Register
uint8_t apUART_Get_ITStatus(UART_TypeDef* pBase,uint8_t UART_IT)
{
	return ( (pBase->IntRaw >> UART_IT) & BW2M(UART_IT) );
}




//
void apUART_Enable_TRANSMIT_INT(UART_TypeDef* pBase)
{
	pBase->IntMask |= 1<<bsUART_TRANSMIT_INTENAB;
}

void apUART_Disable_TRANSMIT_INT(UART_TypeDef* pBase)
{
	pBase->IntMask &= ~(1<<bsUART_TRANSMIT_INTENAB);
}

void apUART_Enable_RECEIVE_INT(UART_TypeDef* pBase)
{
	pBase->IntMask |= 1<<bsUART_RECEIVE_INTENAB;
}
void apUART_Disable_RECEIVE_INT(UART_TypeDef* pBase)
{
	pBase->IntMask &= ~(1<<bsUART_RECEIVE_INTENAB);
}

////////////////////////////////////////////add for controller
void apUART_Clr_RECEIVE_INT(UART_TypeDef* pBase)
{
    pBase->IntClear |= (1<<UART_RECEIVE_INTCLR);
}

void apUART_Clr_TX_INT(UART_TypeDef* pBase)
{
    pBase->IntClear |= (1<<bsUART_TRANSMIT_INTENAB);
}

uint32_t apUART_Get_all_raw_int_stat(UART_TypeDef* pBase)
{
    return (pBase->IntRaw);
}

void apUART_Clr_NonRx_INT(UART_TypeDef* pBase)
{
    pBase->IntClear &= (~(1<<UART_RECEIVE_INTCLR));
}


static void uart_disable(UART_TypeDef* pBase)
{
    pBase->Control &= (~(1<<bsUART_ENABLE));
}

static void uart_enable(UART_TypeDef* pBase)
{
    pBase->Control |= (1<<bsUART_ENABLE);
}


static void uart_empty_fifo(UART_TypeDef* pBase)
{
    pBase->LineCon_H &= (~(1<<bsUART_FIFO_ENABLE));
}

static void uart_enable_fifo(UART_TypeDef* pBase)
{
    pBase->LineCon_H &= (~(1<<bsUART_FIFO_ENABLE));
}


void uart_reset(UART_TypeDef* pBase)
{
	apUART_Disable_RECEIVE_INT(pBase);

	uart_disable(pBase);

	while (apUART_Check_RXFIFO_EMPTY(pBase) != 1)
	{
		volatile uint32_t trash = pBase->DataRead;
        (void)trash;
	}

	uart_empty_fifo(pBase);

	uart_enable_fifo(pBase);

	uart_enable(pBase);

	apUART_Enable_RECEIVE_INT(pBase);

}



//
void apUART_Initialize (UART_TypeDef* pBase, UART_sStateStruct* UARTx, uint32_t IntMask)
{
	// clear Control Register, UARTCR
	pBase->Control = 0;
	// clear all interrupt
	pBase->IntClear = 0;
	// clear all interrupt mask bit
	pBase->IntMask = 0;
	// clear Receive Status Register/Error Clear Register, UARTRSR/UARTECR
	pBase->StatusClear = 0;
	// clear Integer Baud Rate Register, UARTIBRD
	pBase->IntBaudDivisor = 0;
	// clear Fractional Baud Rate Register, UARTFBRD
	pBase->FractBaudDivisor = 0;
	// clear Line Control Register, UARTLCR_H
	pBase->LineCon_H = 0;
	// set BaudDivisor
	apUART_BaudRateSet(pBase, UARTx->ClockFrequency, UARTx->BaudRate);
    // set Line Control Register, UARTLCR_H
	pBase->LineCon_H = ( ((UARTx->parity >> 2) & 1) << bsUART_STICK_PARITY ) |  // SPS
                     (   UARTx->word_length       << bsUART_WORD_LENGTH  ) |  // WLEN
                     (   UARTx->fifo_enable       << bsUART_FIFO_ENABLE  ) |  // FEN
                     (   UARTx->two_stop_bits     << bsUART_TWO_STOP_BITS) |  // STP2
                     ( ( UARTx->parity       & 3) << bsUART_PARITY_SELECT) ;  // EPS, EPN

    // set Interrupt FIFO Level Select Register, UARTIFLS
    pBase->FifoSelect = (UARTx->txfifo_waterlevel << bsUART_TRANS_INT_LEVEL ) | // TXIFLSEL
                      (UARTx->rxfifo_waterlevel << bsUART_RECV_INT_LEVEL  ) ; // RXIFLSEL

    /* Empty the receive FIFO */

	//	set all interrupt mask bit
    pBase->IntMask = IntMask;

    // set Control Register, UARTCR, at last
    pBase->Control = UARTx->receive_en  << bsUART_RECEIVE_ENABLE |
                    UARTx->transmit_en << bsUART_TRANSMIT_ENABLE |
                    UARTx->UART_en     << bsUART_ENABLE          |
                    UARTx->cts_en      << bsUART_CTS_ENA         |
                    UARTx->rts_en      << bsUART_RTS_ENA;

}

void UART_SendData(UART_TypeDef* pBase, uint8_t Data)
{
	pBase->DataRead = Data;
}

uint8_t UART_ReceData(UART_TypeDef* pBase)
{
	return pBase->DataRead;
}

#if (INGCHIPS_FAMILY == INGCHIPS_FAMILY_916)
void UART_DmaEnable(UART_TypeDef *pBase, uint8_t tx_enable, uint8_t rx_enable, uint8_t dma_on_err)
{
    pBase->DmaCon = rx_enable | (tx_enable << 1) | (dma_on_err << 2);
}
#endif
